﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ClientNodeGui
{
	public partial class MainWindow : Form
	{
		#region data members
		protected System.Windows.Forms.NotifyIcon notifyIcon;
		protected ClientNodeLib.SimpleSchedulerClient schedulerClient;
		/// <summary>
		/// Prevents annoying refresh when no state change occurs
		/// </summary>
		private bool lastAcceptJobState;
		#endregion

		public MainWindow()
		{
			InitializeComponent();
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			String title = String.Format(ClientGuiSettings.Default.ClientTitleFormatString, ClientGuiSettings.Default.NotifyIconText, ClientGuiSettings.Default.ClientVersionString);

			// create the notification icon so minimized program disappears
			this.Text = title;
			this.Icon = CommonLib.CommonResources.CommonIcon;
			notifyIcon = new NotifyIcon();
			notifyIcon.Text = title;
			//notifyIcon.Icon = SystemIcons.Exclamation;
			notifyIcon.Icon = CommonLib.CommonResources.CommonIcon;
			notifyIcon.Visible = true;
			notifyIcon.Click += new EventHandler(this.HandleRestore);
			notifyIcon.ContextMenu = new ContextMenu();

			notifyIcon.ContextMenu.MenuItems.Add(new MenuItem("Restore", new EventHandler(this.HandleRestore)));
			notifyIcon.ContextMenu.MenuItems.Add(new MenuItem("Minimize", new EventHandler(this.HandleMinimize)));
			notifyIcon.ContextMenu.MenuItems.Add(new MenuItem("Exit", new EventHandler(this.HandleClose)));

			schedulerClient = new ClientNodeLib.SimpleSchedulerClient();
			schedulerClient.OnNodeDescriptionChange += new ClientNodeLib.UpdateStringEvent(this.UpdateNodeDescription);
			schedulerClient.OnNodeIpChange += new ClientNodeLib.UpdateStringEvent(this.UpdateNodeIpAddress);
			schedulerClient.OnNodeLastStatusReportChange += new ClientNodeLib.UpdateStringEvent(this.UpdateServerConnection);
			schedulerClient.OnNodeNameChange += new ClientNodeLib.UpdateStringEvent(this.UpdateNodeName);
			schedulerClient.OnNodeStateChange += new ClientNodeLib.UpdateStringEvent(this.UpdateNodeState);
			schedulerClient.OnNodeAcceptJobChange += new ClientNodeLib.UpdateStringEvent(this.UpdateNodeAcceptJobState);
			schedulerClient.OnNodeServerAddressChange += new ClientNodeLib.UpdateStringEvent(this.UpdateServerName);
			schedulerClient.Start();

			lastAcceptJobState = !schedulerClient.Settings.AcceptNewJobs; // ensure first time is update
			UpdateStateToolBarText();
			toolStripKillJob.Enabled = false;
		}

		protected override void OnClosed(EventArgs e)
		{
			base.OnClosed(e);
			schedulerClient.Stop();
			notifyIcon.Visible = false;
			notifyIcon.Dispose();
		}

		#region update gui info

		public void UpdateNodeName(String name)
		{
			try
			{
				if (txtNodeName.InvokeRequired)
				{
					NotifyRefresh d = new NotifyRefresh(this.UpdateNodeName);
					this.Invoke(d, name);
				}
				else
				{
					this.txtNodeName.Text = name;
				}
			}
			catch (Exception)
			{

			}
		}

		public void UpdateNodeIpAddress(String ipAddress)
		{
			try
			{
				if (txtNodeIPAddress.InvokeRequired)
				{
					NotifyRefresh d = new NotifyRefresh(this.UpdateNodeIpAddress);
					this.Invoke(d, ipAddress);
				}
				else
				{
					this.txtNodeIPAddress.Text = ipAddress;
				}
			}
			catch (Exception)
			{

			}
		}

		public void UpdateNodeState(String state)
		{
			try
			{
				if (txtNodeState.InvokeRequired)
				{
					NotifyRefresh d = new NotifyRefresh(this.UpdateNodeState);
					this.Invoke(d, state);
				}
				else
				{
					this.txtNodeState.Text = state;

					// TODO: check whether idle for enabled state
					this.toolStripKillJob.Enabled = !state.Equals("Idle");

				}
			}
			catch (Exception)
			{

			}
		}

		public void UpdateNodeDescription(String description)
		{
			try
			{
				if (txtDescription.InvokeRequired)
				{
					NotifyRefresh d = new NotifyRefresh(this.UpdateNodeDescription);
					this.Invoke(d, description);
				}
				else
				{
					this.txtDescription.Text = description;
				}
			}
			catch (Exception)
			{

			}
		}

		public void UpdateServerConnection(String connectionDesc)
		{
			try
			{
				if (txtServerConnection.InvokeRequired)
				{
					NotifyRefresh d = new NotifyRefresh(this.UpdateServerConnection);
					this.Invoke(d, connectionDesc);
				}
				else
				{
					this.txtServerConnection.Text = connectionDesc;
				}
			}
			catch (Exception)
			{

			}
		}

		public void UpdateServerName(String connectionDesc)
		{
			try
			{
				if (txtServerName.InvokeRequired)
				{
					NotifyRefresh d = new NotifyRefresh(this.UpdateServerName);
					this.Invoke(d, connectionDesc);
				}
				else
				{
					this.txtServerName.Text = connectionDesc;
				}
			}
			catch (Exception)
			{

			}
		}

		public void UpdateNodeAcceptJobState(String newState)
		{
			UpdateStateToolBarText();
		}
		private delegate void NotifyRefresh(String newString);
		#endregion

		#region window management

		protected override void OnResize(EventArgs e)
		{
			base.OnResize(e);
			if (this.WindowState == FormWindowState.Minimized)
			{
				this.ShowInTaskbar = false;
			}
		}

		public void HandleClose(Object o, EventArgs args)
		{
			this.Close();
		}

		public void HandleMinimize(Object o, EventArgs args)
		{
			this.WindowState = FormWindowState.Minimized;
			this.ShowInTaskbar = false;
		}

		public void HandleRestore(Object o, EventArgs args)
		{
			this.WindowState = FormWindowState.Normal;
			this.ShowInTaskbar = true;
		}
		#endregion

		#region event handlers
		private void toolStripOptions_Click(object sender, EventArgs e)
		{
			if (schedulerClient == null)
				return;
			ClientOptionsDialog od = new ClientOptionsDialog();
			od.NodeName = schedulerClient.Settings.NodeName;
			od.LongTimeout = (int)schedulerClient.Settings.LongTimeout.TotalSeconds;
			od.ShortTimeout = (int)schedulerClient.Settings.ShortTimeout.TotalSeconds;
			od.ServerAddress = schedulerClient.Settings.ServerAddress;
			od.AllowServerControl = schedulerClient.Settings.AllowServerControl;
			if (od.ShowDialog() == DialogResult.OK)
			{
				schedulerClient.Settings.NodeName = od.NodeName;
				schedulerClient.Settings.LongTimeout = TimeSpan.FromSeconds(od.LongTimeout);
				schedulerClient.Settings.ShortTimeout = TimeSpan.FromSeconds(od.ShortTimeout);
				schedulerClient.Settings.AllowServerControl = od.AllowServerControl;
				schedulerClient.Settings.ServerAddress = od.ServerAddress;
			}
		}

		private void toolStripKillJob_Click(object sender, EventArgs e)
		{
			if (schedulerClient != null)
				schedulerClient.KillJob();
		}

		private void toolStripState_Click(object sender, EventArgs e)
		{
			if (schedulerClient == null)
				return;

			schedulerClient.Settings.AcceptNewJobs = !schedulerClient.Settings.AcceptNewJobs;
			UpdateStateToolBarText();
		}

		

		private void UpdateStateToolBarText()
		{
			if (schedulerClient.Settings.AcceptNewJobs == lastAcceptJobState)
				return;

			if (schedulerClient.Settings.AcceptNewJobs)
			{
				toolStripState.Image = GuiResources.StateGoImage;
				toolStripState.Text = GuiResources.ToolStripAcceptNewJobs;
			}
			else
			{
				toolStripState.Image = GuiResources.StateStopImage;
				toolStripState.Text = GuiResources.ToolStripAcceptNoJobs;
			}
			lastAcceptJobState = schedulerClient.Settings.AcceptNewJobs;
		}
		#endregion
	}
}
